package cn.sskxyz.mongodb.multi;

import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MongDbLinkAspect {

	@Pointcut("@within(cn.sskxyz.mongodb.multi.MongoLink)")
	private void typeAnnotation() {

	}

	@Pointcut("@annotation(cn.sskxyz.mongodb.multi.MongoLink)")
	private void methodAnnotation() {

	}

	@Pointcut("methodAnnotation() || typeAnnotation()")
	public void selectDatasource() {

	}

	@Before(value = "selectDatasource()")
	public void before(JoinPoint jPoint) throws NoSuchMethodException {
		MongoLink mongoLink = getMethodMongoLinkAnnotation(jPoint);
		if(mongoLink == null) {
			mongoLink = getClassMongoLinkAnnotation(jPoint);
		}
		MongoDbLinkHolder.bind(new MongoLinkContext(mongoLink.link(), mongoLink.database()));
	}

	@After("selectDatasource()")
	public void after() {
		MongoDbLinkHolder.unbind();
	}

	private MongoLink getClassMongoLinkAnnotation(JoinPoint joinPoint) {
		Class<?> targetClass = joinPoint.getTarget().getClass();
		return targetClass.getAnnotation(MongoLink.class);
	}

	private MongoLink getMethodMongoLinkAnnotation(JoinPoint joinPoint) throws NoSuchMethodException {
		Class<?> targetClass = joinPoint.getTarget().getClass();
		String methodName = joinPoint.getSignature().getName();
		Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
		Method method = targetClass.getMethod(methodName, parameterTypes);
		return method.getAnnotation(MongoLink.class);
	}
}
